package com.example.monitoring.scheduler;

import com.example.monitoring.config.MonitoringProperties;
import com.example.monitoring.model.MonitoringResult;
import com.example.monitoring.model.MonitoringStatus;
import com.example.monitoring.service.MonitoringService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 监控调度器类
 * 
 * @author rsz
 * @since 2024-04-13
 */
@Slf4j
@Component
public class MonitoringScheduler {

    private final MonitoringService monitoringService;
    private final MonitoringProperties properties;
    
    // 标记目标服务是否健康（多服务）
    private List<Boolean> targetServicesHealthy = new ArrayList<>();
    
    // 记录上次异常导出报表的时间，避免频繁导出
    private LocalDateTime lastExceptionReportTime = null;
    
    // 异常报表导出间隔（分钟）
    private static final int EXCEPTION_REPORT_INTERVAL_MINUTES = 30;

    public MonitoringScheduler(MonitoringService monitoringService, MonitoringProperties properties) {
        this.monitoringService = monitoringService;
        this.properties = properties;
        
        // 初始化时，假设所有服务都是健康的
        if (properties.getTargetService() != null) {
            for (int i = 0; i < properties.getTargetService().size(); i++) {
                targetServicesHealthy.add(true);
            }
        }
    }

    /**
     * 定时检查目标服务健康状态
     */
    @Scheduled(fixedDelay = 180000) // 3分钟检查一次
    public void checkTargetServiceHealth() {
        log.debug("开始定时检查目标服务健康状态");
        
        if (properties.getTargetService() == null || properties.getTargetService().isEmpty()) {
            log.warn("未配置目标服务，跳过健康检查");
            return;
        }
        
        List<Boolean> currentHealthStatus = monitoringService.checkAllTargetServicesHealth();
        boolean anyServiceUnhealthy = false;
        boolean anyStatusChanged = false;
        
        // 确保状态列表和服务数量一致
        while (targetServicesHealthy.size() < currentHealthStatus.size()) {
            targetServicesHealthy.add(true);
        }
        
        // 检查每个服务的状态变化
        for (int i = 0; i < currentHealthStatus.size(); i++) {
            boolean isCurrentlyHealthy = currentHealthStatus.get(i);
            
            // 如果服务索引超出范围，则初始化
            if (i >= targetServicesHealthy.size()) {
                targetServicesHealthy.add(isCurrentlyHealthy);
                continue;
            }
            
            boolean wasHealthy = targetServicesHealthy.get(i);
            
            if (wasHealthy && !isCurrentlyHealthy) {
                // 服务从健康变为不健康
                String serviceName = properties.getTargetService().get(i).getName();
                log.warn("目标服务 [{}] 变为不健康状态", serviceName);
                anyStatusChanged = true;
                anyServiceUnhealthy = true;
            } else if (!wasHealthy && isCurrentlyHealthy) {
                // 服务恢复健康
                String serviceName = properties.getTargetService().get(i).getName();
                log.info("目标服务 [{}] 恢复健康状态", serviceName);
                anyStatusChanged = true;
            }
            
            // 更新健康状态
            targetServicesHealthy.set(i, isCurrentlyHealthy);
            
            // 检查是否有不健康的服务
            if (!isCurrentlyHealthy) {
                anyServiceUnhealthy = true;
            }
        }
        
        // 如果有服务状态变化且至少有一个服务不健康，则启动完整监控并导出报表
        if (anyStatusChanged && anyServiceUnhealthy) {
            log.warn("检测到服务状态变化且有不健康服务，启动完整监控");
            startComprehensiveMonitoring();
            exportExceptionReport("目标服务异常");
        }
    }
    
    /**
     * 定时检查网络连通性
     */
    @Scheduled(fixedDelay = 300000) // 5分钟检查一次
    public void checkNetworkConnectivity() {
        log.debug("开始定时检查网络连通性");
        
        try {
            List<MonitoringResult> networkResults = monitoringService.checkNetworkConnectivity();
            
            // 检查是否有网络连接异常
            boolean hasNetworkIssue = false;
            for (MonitoringResult result : networkResults) {
                if (result.getStatus() == MonitoringStatus.ERROR || result.getStatus() == MonitoringStatus.WARNING) {
                    log.warn("网络连接异常: {} - {}", result.getName(), result.getDetails());
                    hasNetworkIssue = true;
                }
            }
            
            // 如果有网络异常，导出报表
            if (hasNetworkIssue) {
                exportExceptionReport("网络连接异常");
            }
            
        } catch (Exception e) {
            log.error("网络连通性检查过程中发生错误", e);
            exportExceptionReport("网络连通性检查异常");
        }
    }
    
    /**
     * 定时监控系统资源
     */
    @Scheduled(fixedDelay = 1800000) // 30分钟检查一次
    public void monitorSystemResources() {
        log.debug("开始定时监控系统资源");
        
        try {
            MonitoringResult systemResult = monitoringService.monitorSystem();
            
            // 检查系统资源是否异常
            if (systemResult.getStatus() == MonitoringStatus.ERROR || systemResult.getStatus() == MonitoringStatus.WARNING) {
                log.warn("系统资源异常: {} - {}", systemResult.getName(), systemResult.getDetails());
                exportExceptionReport("系统资源异常");
            }
            
        } catch (Exception e) {
            log.error("系统资源监控过程中发生错误", e);
            exportExceptionReport("系统资源监控异常");
        }
    }
    
    /**
     * 定时监控中间件健康状态
     */
    @Scheduled(fixedDelay = 900000) // 15分钟检查一次
    public void monitorMiddlewareHealth() {
        log.debug("开始定时监控中间件健康状态");
        
        try {
            boolean hasMiddlewareIssue = false;
            
            // 监控JVM
            if (properties.getMiddleware().getJvm().isEnabled()) {
                MonitoringResult jvmResult = monitoringService.monitorJvm();
                if (jvmResult.getStatus() == MonitoringStatus.ERROR || jvmResult.getStatus() == MonitoringStatus.WARNING) {
                    log.warn("JVM异常: {}", jvmResult.getDetails());
                    hasMiddlewareIssue = true;
                }
            }
            
            // 监控Redis
            if (properties.getMiddleware().getRedis().isEnabled()) {
                MonitoringResult redisResult = monitoringService.monitorRedis();
                if (redisResult.getStatus() == MonitoringStatus.ERROR || redisResult.getStatus() == MonitoringStatus.WARNING) {
                    log.warn("Redis异常: {}", redisResult.getDetails());
                    hasMiddlewareIssue = true;
                }
            }
            
            // 监控Elasticsearch
            if (properties.getMiddleware().getElasticsearch().isEnabled()) {
                MonitoringResult esResult = monitoringService.monitorElasticsearch();
                if (esResult.getStatus() == MonitoringStatus.ERROR || esResult.getStatus() == MonitoringStatus.WARNING) {
                    log.warn("Elasticsearch异常: {}", esResult.getDetails());
                    hasMiddlewareIssue = true;
                }
            }
            
            // 监控MySQL
            if (properties.getMiddleware().getMysql().isEnabled()) {
                MonitoringResult mysqlResult = monitoringService.monitorMysql();
                if (mysqlResult.getStatus() == MonitoringStatus.ERROR || mysqlResult.getStatus() == MonitoringStatus.WARNING) {
                    log.warn("MySQL异常: {}", mysqlResult.getDetails());
                    hasMiddlewareIssue = true;
                }
            }
            
            // 监控MinIO
            if (properties.getMiddleware().getMinio().isEnabled()) {
                MonitoringResult minioResult = monitoringService.monitorMinio();
                if (minioResult.getStatus() == MonitoringStatus.ERROR || minioResult.getStatus() == MonitoringStatus.WARNING) {
                    log.warn("MinIO异常: {}", minioResult.getDetails());
                    hasMiddlewareIssue = true;
                }
            }
            
            // 如果有中间件异常，导出报表
            if (hasMiddlewareIssue) {
                exportExceptionReport("中间件异常");
            }
            
        } catch (Exception e) {
            log.error("中间件健康状态监控过程中发生错误", e);
            exportExceptionReport("中间件监控异常");
        }
    }
    
    /**
     * 每天定时导出监控报告
     */
    // @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    // public void exportDailyReport() {
    //     log.info("开始导出每日监控报告");
    //     try {
    //         String reportPath = monitoringService.exportReport();
    //         log.info("每日监控报告导出完成: {}", reportPath);
    //     } catch (Exception e) {
    //         log.error("每日监控报告导出失败", e);
    //     }
    // }
    
    /**
     * 启动完整监控（包括所有中间件和系统资源）
     */
    private void startComprehensiveMonitoring() {
        log.info("启动完整监控（中间件 + 系统资源 + 网络连通性）");
        
        try {
            // 监控所有中间件
            startMiddlewareMonitoring();
            
            // 监控系统资源
            log.info("执行系统资源监控");
            monitoringService.monitorSystem();
            
            // 检查网络连通性
            log.info("执行网络连通性检查");
            monitoringService.checkNetworkConnectivity();
            
        } catch (Exception e) {
            log.error("完整监控过程中发生错误", e);
        }
    }
    
    /**
     * 启动中间件监控
     */
    private void startMiddlewareMonitoring() {
        log.info("启动所有中间件监控");
        
        try {
            // 监控JVM
            if (properties.getMiddleware().getJvm().isEnabled()) {
                log.debug("执行JVM监控");
                monitoringService.monitorJvm();
            }
            
            // 监控Redis
            if (properties.getMiddleware().getRedis().isEnabled()) {
                log.debug("执行Redis监控");
                monitoringService.monitorRedis();
            }
            
            // 监控Elasticsearch
            if (properties.getMiddleware().getElasticsearch().isEnabled()) {
                log.debug("执行Elasticsearch监控");
                monitoringService.monitorElasticsearch();
            }
            
            // 监控MySQL
            if (properties.getMiddleware().getMysql().isEnabled()) {
                log.debug("执行MySQL监控");
                monitoringService.monitorMysql();
            }
            
            // 监控MinIO
            if (properties.getMiddleware().getMinio().isEnabled()) {
                log.debug("执行MinIO监控");
                monitoringService.monitorMinio();
            }
        } catch (Exception e) {
            log.error("中间件监控过程中发生错误", e);
        }
    }
    
    /**
     * 异常时导出报表（带频率限制）
     * 
     * @param reason 导出原因
     */
    private void exportExceptionReport(String reason) {
        LocalDateTime now = LocalDateTime.now();
        
        // 检查是否需要限制导出频率
        if (lastExceptionReportTime != null) {
            long minutesSinceLastReport = java.time.Duration.between(lastExceptionReportTime, now).toMinutes();
            if (minutesSinceLastReport < EXCEPTION_REPORT_INTERVAL_MINUTES) {
                log.debug("距离上次异常报表导出时间不足{}分钟，跳过本次导出。原因: {}", 
                    EXCEPTION_REPORT_INTERVAL_MINUTES, reason);
                return;
            }
        }
        
        try {
            log.warn("检测到异常，开始导出监控报表。原因: {}", reason);
            String reportPath = monitoringService.exportReport();
            lastExceptionReportTime = now;
            
            String timestamp = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            log.warn("异常监控报表导出完成: {} (时间: {}, 原因: {})", reportPath, timestamp, reason);
            
        } catch (Exception e) {
            log.error("异常监控报表导出失败，原因: {}", reason, e);
        }
    }
} 